package com.sudo.service.aspect;

import com.sudo.common.enums.SysJobAction;
import com.sudo.common.enums.ThrowOrReturn;
import com.sudo.common.exception.BizException;
import com.sudo.common.service.BaseService;
import com.sudo.common.task.TaskUtil;
import com.sudo.common.utils.*;
import com.sudo.starter.log.constant.LogConstant;
import com.sudo.service.admin.runnable.NextJobUtil;
import com.sudo.service.admin.service.LogAndEmailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
@Aspect
@Component
public class VerifyTaskRequestAspect{

    @Resource
    private LogAndEmailService logAndEmailService;

    // 配置织入点
    @Pointcut("@annotation(com.sudo.service.annotation.VerifyTaskRequest)")
    public void pointCut() {
    }

    /**
     * 前置通知：用于拦截操作
     * @param joinPoint 切入点
     */
    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        String simpleName = StringUtils.uncapitalize(joinPoint.getTarget().getClass().getSimpleName());
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        int parameterCount = method.getParameterCount();
        // 有参数
        if (parameterCount > 0){
            Map<String,Object> objectMap = (Map<String,Object>)joinPoint.getArgs()[0];
            if (!TaskUtil.verifyParam(simpleName, method.getName(),objectMap)) {
                log.error("定时任务《{}》参数校验不通过，任务暂停执行！",method.getName());
                throw new BizException("执行中止：参数校验不通过！");
            }
        }
        log.info("method任务开始执行：{}#{}",simpleName,method.getName());
    }


    @AfterReturning(value = "pointCut()")
    public void doAfterReturning(){
        JsonRes jsonRes = JsonRes.okMsg("任务执行成功！");
        HttpServletResponse response = HttpServletUtil.getResponse();
        Map<String, Object> tlMap = ThreadLocalUtil.getTlMap();
        log.info("method任务执行成功");
        ThreadLocalUtil.removeTlMap();
        // 运行子任务
        int jobId = Integer.parseInt(tlMap.get("tl_jobId").toString());
        NextJobUtil.runNextMethodJobs(jobId, ThrowOrReturn.RETURN);
        MDC.clear();
        if (response == null) {
            logAndEmailService.asyncLocalMethodJobLogAndEmail(tlMap,jsonRes, SysJobAction.AUTO);
        }else {
            logAndEmailService.asyncLocalMethodJobLogAndEmail(tlMap,jsonRes, SysJobAction.MANUAL);
            RetResponse.res(response,jsonRes);
        }
    }

    @AfterThrowing(value = "pointCut()",throwing = "throwable")
    public void doAfterThrowing(Throwable throwable){
        JsonRes jsonRes = JsonRes.errorMsg("执行中止：后端服务异常！");
        jsonRes.setData(ExceptionUtils.getStackTrace(throwable));
        HttpServletResponse response = HttpServletUtil.getResponse();
        Map<String, Object> tlMap = ThreadLocalUtil.getTlMap();
        log.error("method任务执行失败");
        ThreadLocalUtil.removeTlMap();
        // 运行子任务
        int jobId = Integer.parseInt(tlMap.get("tl_jobId").toString());
        NextJobUtil.runNextMethodJobs(jobId, ThrowOrReturn.THROW);
        MDC.clear();
        if (response == null) {
            logAndEmailService.asyncLocalMethodJobLogAndEmail(tlMap,jsonRes, SysJobAction.AUTO);
        }else {
            logAndEmailService.asyncLocalMethodJobLogAndEmail(tlMap,jsonRes, SysJobAction.MANUAL);
            RetResponse.res(response,jsonRes);
        }
    }

}
